/* Copyright (C) 2024 wlly-lzh
 * Created On 24/03/23
 * Linked List Stack 基于链表的栈
 * */

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "linkedlist.c"

typedef struct LLinStack LLinStack;
struct LLinStack {
	struct LinkedList * List;
	int Length;
};

void Error_LLinStack_Malloc();
void Error_LLinStack_NULL();
void Error_LLinStack_Empty();

LLinStack * Create_LLinStack(){
	LLinStack * newStack;
	newStack =(LLinStack *)malloc(sizeof(LLinStack));
	if(newStack == NULL){
		Error_LLinStack_Malloc();
		exit(3);
	}
	newStack->Length=0;
	newStack->List=NULL;
	return newStack;
}

void Clear_LLinStack(LLinStack *Stack){
	if(Stack != NULL){
		if(Stack->Length > 0){
			Clear_LinkedList(Stack->List);
			Stack->Length=0;
		}
	}else{
		Error_LLinStack_NULL();
		exit(4);
	}
}

void Destroy_LLinStack(LLinStack **Stack){
	Clear_LLinStack(*Stack);
	free(*Stack);
	*Stack=NULL;
}

bool Push_LLinStack(LLinStack *Stack, void *Data){
	if(Stack == NULL){
		Error_LLinStack_NULL();
		exit(4);
	}
	if(Data != NULL){
		LinkedList *newList=(LinkedList *)malloc(sizeof(LinkedList));
		if(newList == NULL){
			Error_LLinStack_Malloc();
			exit(3);
		}
		newList->Data=Data;
		newList->Next=Stack->List;
		Stack->List=newList; // 在链表的头部插入，同样也在头部读取
		Stack->Length++;
		return true;
	}else{
		Error_LLinStack_NULL();
		return false;
	}
}
bool Pop_LLinStack(LLinStack *Stack, void **Data){
	if(Stack == NULL){
		Error_LLinStack_NULL();
		exit(4);
	}
	LinkedList *Del=Stack->List;
	if(Stack->Length > 0){ //防止空栈被Pop
		*Data=Stack->List->Data;
		Stack->List=Stack->List->Next; // Pop之后栈顶改变
		free(Del);
		Stack->Length--;
		return true;
	}else{
		Error_LLinStack_Empty();
		return false;
	}
}
bool GetTop_LLinStack(const LLinStack *Stack, void **Data){
	if(Stack == NULL){
		Error_LLinStack_NULL();
		exit(4);
	}
	if(Stack->Length > 0){
		*Data=Stack->List->Data;
		return true;
	}else{
		Error_LLinStack_Empty();
		return false;
	}
}
bool IsEmpty_LLinStack(const LLinStack *Stack){
	if(Stack == NULL){
		Error_LLinStack_NULL();
		exit(4);
	}
	if(Stack->Length == 0)
		return true;
	else
		return false;
}
int Size_LLinStack(const LLinStack *Stack){
	if(Stack == NULL){
		Error_LLinStack_NULL();
		exit(4);
	}
	return Stack->Length;
}

#ifdef _LINUX_PLATFORM_
void Error_LLinStack_Malloc(){
	printf("\033[31mliblds:LLinStack: Malloc False!\033[0m\n");
}
void Error_LLinStack_NULL(){
	printf("\033[31mliblds:LLinStack: The parameter is NUll!\033[0m\n");
}
void Error_LLinStack_Empty(){
	printf("\033[31mliblds:LLinStack: The Stack Is Empty!\033[0m\n");
}
#else
void Error_LLinStack_Malloc(){
	printf("liblds:LLinStack: Malloc False!\n");
}
void Error_LLinStack_NULL(){
	printf("liblds:LLinStack: The parameter is NUll!\n");
}
void Error_LLinStack_Empty(){
	printf("liblds:LLinStack: The Stack Is Empty!\n");
}
#endif // _LINUX_PLATFORM_
